package com.english.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.english.entity.FreeLessonAppointment;
import com.english.entity.FreeLessonTimeSlot;
import com.english.mapper.FreeLessonAppointmentMapper;
import com.english.mapper.FreeLessonTimeSlotMapper;
import com.english.service.FreeLessonAppointmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.time.LocalDate;

@Service
public class FreeLessonAppointmentServiceImpl implements FreeLessonAppointmentService {

    @Autowired
    private FreeLessonAppointmentMapper appointmentMapper;
    @Autowired
    private FreeLessonTimeSlotMapper timeSlotMapper;

    @Override
    @Transactional
    public void createAppointment(FreeLessonAppointment appointment) {
        // 检查学生是否在本周已有预约
        if (hasWeeklyAppointment(appointment.getStudentId(), appointment.getAppointmentDate())) {
            throw new RuntimeException("每个学生一周只能预约一次免费小课");
        }

        FreeLessonTimeSlot slot = timeSlotMapper.selectById(appointment.getTimeSlotId());
        System.err.println(slot);
        if (slot == null || slot.getStatus() != 1 || slot.getIsOccupied() == 1 ) {
            throw new RuntimeException("该时段不可预约");
        }
        appointment.setStatus("PENDING");
        appointment.setCreateTime(new Date());
        appointmentMapper.insert(appointment);
        slot.setCurrentStudents(slot.getCurrentStudents() + 1);
        if (slot.getCurrentStudents() >= slot.getMaxStudents()) {
            slot.setIsOccupied(0);
        }
        timeSlotMapper.updateById(slot);
    }

    @Override
    @Transactional
    public boolean cancelAppointment(Long appointmentId, String cancelReason) {
        FreeLessonAppointment appointment = appointmentMapper.selectById(appointmentId);
        if (appointment == null) {
            throw new RuntimeException("预约不存在");
        }

        // 如果已经是取消状态，返回false表示无需操作
        if ("CANCELLED".equals(appointment.getStatus())) {
            return false;
        }

        // 只允许PENDING或CONFIRMED状态的预约被取消
        if (!("PENDING".equals(appointment.getStatus()) || "CONFIRMED".equals(appointment.getStatus()))) {
            throw new RuntimeException("预约不可取消");
        }

        appointment.setStatus("CANCELLED");
        appointment.setCancelReason(cancelReason);
        appointmentMapper.updateById(appointment);
        FreeLessonTimeSlot slot = timeSlotMapper.selectById(appointment.getTimeSlotId());
        slot.setCurrentStudents(slot.getCurrentStudents() - 1);
        if (slot.getCurrentStudents() < slot.getMaxStudents()) {
            slot.setIsOccupied(0);
        }
        timeSlotMapper.updateById(slot);

        return true;
    }

    @Override
    @Transactional
    public void updateStatus(Long appointmentId, String status, Long adminId) {
        FreeLessonAppointment appointment = appointmentMapper.selectById(appointmentId);
        appointment.setStatus(status);
        if ("CONFIRMED".equals(status)) {
            appointment.setConfirmedBy(adminId);
            appointment.setConfirmedTime(new Date());
        }
        appointmentMapper.updateById(appointment);
    }

    @Override
    public List<FreeLessonAppointment> queryAppointments(Long studentId, String date, String status) {
        // 使用关联查询获取学生姓名
        return appointmentMapper.selectAppointmentsWithStudentName(studentId, date, status);
    }

    @Override
    public boolean canStudentAppointment(Long studentId, String date) {
        LocalDate appointmentDate = LocalDate.parse(date);
        return !hasWeeklyAppointment(studentId, appointmentDate);
    }

    /**
     * 检查学生是否在本周已有预约
     * @param studentId 学生ID
     * @param appointmentDate 预约日期
     * @return 是否已有预约
     */
    private boolean hasWeeklyAppointment(Long studentId, LocalDate appointmentDate) {
        // 计算本周的开始和结束日期
        LocalDate weekStart = appointmentDate.with(java.time.DayOfWeek.MONDAY);
        LocalDate weekEnd = weekStart.plusDays(6);

        QueryWrapper<FreeLessonAppointment> qw = new QueryWrapper<>();
        qw.eq("student_id", studentId)
          .between("appointment_date", weekStart, weekEnd)
          .in("status", "PENDING", "CONFIRMED");

        return appointmentMapper.selectCount(qw) > 0;
    }
}
